﻿// Copyright 2008 Newgrove Consultants Limited
// Modified By John Diss 
//
using System;
using System.Collections.Generic;
using GeoAPI.DataStructures;

namespace GeoAPI.Geometries
{
    public static class GeometryUtilities
    {
        public static double Length(IGeometry geometry)
        {
            if (geometry is ILineString)
                return ((ILineString)geometry).Length;
            if (geometry is IMultiLineString)
                return ((IMultiLineString)geometry).Length;
            return 0;
        }

        public static double Area(IGeometry geometry)
        {
            if (geometry is ISurface)
                return ((ISurface)geometry).Area;
            if (geometry is IMultiSurface)
                return Enumerable.Sum(((IEnumerable<ISurface>)geometry), o => o.Area);
            return 0;
        }

        public static IExtents ExpandBy(IExtents original, double distance)
        {
            throw new NotImplementedException();
        }

        public static int MsSqlSpatialSrid(IGeometry geom)
        {
            int? srid = Global.ParseSridString(geom.Srid);
            return srid.HasValue && srid.Value > 0 ? srid.Value : -1;
        }

        public static IGeometry SetSridNull(IGeometry geometry)
        {
            int? srid = Global.ParseSridString(geometry.Srid);
            if (!srid.HasValue)
                return geometry;

            return Global.Services.GeometryFactory.CreateGeometry(geometry);
        }

        public static IGeometry SetSrid(IGeometry geometry, string srid)
        {
            return SetSrid(geometry, Global.ParseSridString(srid));
        }

        public static IGeometry SetSrid(IGeometry geometry, int? srid)
        {
            if (!srid.HasValue || srid.Value <= 0)
                return SetSridNull(geometry);

            return Global.Services[srid].CreateGeometry(geometry);
        }

        //public static IGeometry SetSrid(IGeometry geometry, SqlInt32 srid)
        //{
        //    if (srid.IsNull)
        //        return SetSridNull(geometry);

        //    throw new NotImplementedException();
        //}
    }

    //    public static class IGeometryExtensions
    //    {
    //        /// <summary>
    //        /// returns the real Srid of the Geometry or -1 if the Srid is null.
    //        /// </summary>
    //        /// <param name="g"></param>
    //        /// <returns></returns>
    //        public static int SridMsSqlSpatial(this IGeometry g)
    //        {
    //            return g.Srid.HasValue ? g.Srid.Value : -1;
    //        }

    //#warning "watch the performance of this. The last version allowed changing of srid"

    //        /// <summary>
    //        /// returns the geometry if the srid is null or a new geometry based on the original but with the SpatialReference System removed
    //        /// </summary>
    //        /// <param name="g"></param>
    //        /// <returns></returns>
    //        public static IGeometry SetSridNull(this IGeometry g)
    //        {
    //            if (!g.Srid.HasValue || g.Srid == -1)
    //                return g;
    //            return Global.Services.GeometryFactory.CreateGeometry(g);
    //        }

    //#warning "watch the performance of this. The last version allowed changing of srid"

    //        public static IGeometry SetSridNull<TCoordinate>(this IGeometry g)
    //            where TCoordinate : ICoordinate<TCoordinate>, IEquatable<TCoordinate>, IComparable<TCoordinate>, IComputable<Double, TCoordinate>, IConvertible
    //        {
    //            if (!g.Srid.HasValue || g.Srid == -1)
    //                return g;

    //            return Global.Services.GeometryFactory.CreateGeometry(g);

    //        }

    //#warning "watch the performance of this. The last version allowed changing of srid"
    //        /// <summary>
    //        /// returns the geometry if it is already in the requested Reference System or 
    //        /// a new geometry based on the original but in the required Spatial Reference System
    //        /// </summary>
    //        /// <param name="g"></param>
    //        /// <param name="srid"></param>
    //        /// <returns></returns>
    //        public static IGeometry SetSrid(this IGeometry g, int? srid)
    //        {
    //            if (srid == g.Srid || g.Srid == -1 && !srid.HasValue)
    //                return g;

    //            return Global.Services[srid].CreateGeometry(g);
    //        }

    //#warning "keep an eye out for changes to GeoAPI"
    //        /// <summary>
    //        /// this is probably incorrect.
    //        /// Waiting to see if it appears back in GeoAPI
    //        /// </summary>
    //        /// <param name="g"></param>
    //        /// <returns></returns>
    //        public static double Area(this IGeometry g)
    //        {
    //            if (g is ISurface)
    //                return ((ISurface)g).Area;
    //            if (g is IGeometryCollection)
    //                return ((IGeometryCollection)g).Sum(o => o.Area());
    //            return 0;
    //        }

    //#warning "keep an eye out for changes to GeoAPI"
    //        /// <summary>
    //        /// this is probably incorrect.
    //        /// Waiting to see if it appears back in GeoAPI
    //        /// </summary>
    //        /// <param name="g"></param>
    //        /// <returns></returns>
    //        public static double Length(this IGeometry g)
    //        {
    //            if (g is ICurve)
    //                return ((ICurve)g).Length;
    //            if (g is IGeometryCollection)
    //                return ((IGeometryCollection)g).Sum(o => o.Length());
    //            return 0;
    //        }

    //        //public static IExtents EnvelopeInternal(this IGeometry g)
    //        //{
    //        //    return g.Extents;
    //        //}

    //        public static void ExpandBy(this IExtents e, double delta)
    //        {
    //            e.ExpandBy(delta, delta);
    //        }

    //        public static void ExpandBy(this IExtents e, double dx, double dy)
    //        {
    //            double minX = e.Min[Ordinates.X] - dx;
    //            double minY = e.Min[Ordinates.Y] - dy;

    //            double maxX = e.Max[Ordinates.X] + dx;
    //            double maxY = e.Max[Ordinates.Y] + dy;


    //            e.ExpandToInclude
    //                (
    //                    minX, minY,
    //                    maxX, maxY
    //                );
    //        }


    //        public static XmlReader ToGMLFeature(this IGeometry g)
    //        {
    //            return GMLWriter.Write(g);
    //        }


    //    }
}